package com.example.tys.daggermvp.view.recyclerviewCompant.sticky;

import android.content.Context;

import com.example.tys.daggermvp.view.recyclerviewCompant.BaseAdapter;
import com.example.tys.daggermvp.view.recyclerviewCompant.BaseViewHolder;

import java.util.ArrayList;
import java.util.List;

/**
 * RecyclerView的粘性基础Adapter。
 * 1.添加了{@link #needTitle(int)}用来判断是否需要显示title。
 * 2.重写数据添加方法。比如{@link #addDataAndNotify(StickyBaseData)}用来在进行数据添加时进行数据的填充(用于GridLayoutManager)
 * 使用时继承该Adapter。请配合{@link StickyItemDivider}，{@link StickyBaseData}一起使用。
 *
 * @author tys
 * @date 2017/10/14
 */
public abstract class StickyBaseAdapter<T extends StickyBaseData, VH extends BaseViewHolder> extends BaseAdapter<T, VH> {
    /**
     * 缓存填充的数据，避免每次反射获取。
     */
    private T filledBean;
    /**
     * 每一行的列数。如果是GridLayoutManager必须设置。
     */
    protected int mSpanCount = 1;

    /**
     * 用于LinearLayoutManager时的构造函数
     *
     * @param context
     * @param mData
     */
    protected StickyBaseAdapter(Context context, ArrayList<T> mData) {
        super(context, mData);
    }

    /**
     * 用于GridLayoutManager的构造函数
     *
     * @param context
     * @param mData
     * @param spanCount 每一行的列数,和GridLayoutManager{@link android.support.v7.widget.GridLayoutManager#mSpanCount}中的参数一致
     */
    protected StickyBaseAdapter(Context context, ArrayList<T> mData, int spanCount) {
        super(context, mData);
        this.mSpanCount = spanCount;
    }

    /**
     * 当前Item是否需要显示title
     *
     * @param position 数组下标
     * @return
     */
    protected boolean needTitle(int position) {
        if (position == 0) {
            return true;
        } else {
            return needTitle(mData.get(position - 1), mData.get(position));
        }
    }

    protected boolean needTitle(StickyBaseData lastTitle, StickyBaseData currentTitle) {
        if (currentTitle.isFilled()) {
            return false;
        }
        return !lastTitle.stickTitle().equals(currentTitle.stickTitle());
    }

    /**
     * 重写进行数据填充。数据(GridView)不满一行时进行数据填充。
     * 根据实际情况，可能会重写更多数据加载方法，以用来进行数据填充
     *
     * @param data 要添加的数据
     */
    @Override
    public void addDataAndNotify(T data) {
        if (mSpanCount == 1) {
            //LinearLayoutManager
            super.addDataAndNotify(data);
        } else {
            //GridLayoutManager
            int start = mData.size();
            if (start == 0 || !needTitle(mData.get(start - 1), data)) {
                mData.add(data);
            } else {
                //不滿一行，进行数据填充
                for (int i = start; i % mSpanCount > 0; i++) {
                    if (null == filledBean) {
                        try {
                            //华为手机反射创建对象，需要有一个无参构造函数
                            filledBean = (T) data.getClass().newInstance();
                            filledBean.setFilled(true);
                        } catch (InstantiationException | IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    mData.add(filledBean);
                }
                mData.add(data);
            }
            notifyItemRangeChanged(start, mData.size());
        }
    }

    @Override
    public void addDataAndNotify(List<T> data) {
        if (mSpanCount == 1) {
            super.addDataAndNotify(data);
            return;
        }
        int start = mData.size();
        for (int i = 0; i < data.size(); i++) {
            if (i == 0 || !needTitle(data.get(i - 1), data.get(i))) {
                mData.add(data.get(i));
            } else {
                int index = mData.size();
                for (int j = index; j % mSpanCount > 0; j++) {
                    if (null == filledBean) {
                        try {
                            //华为手机反射创建对象，需要有一个无参构造函数
                            filledBean = (T) data.get(0).getClass().newInstance();
                            filledBean.setFilled(true);
                        } catch (InstantiationException | IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    mData.add(filledBean);
                }
                mData.add(data.get(i));
            }
        }
        notifyItemRangeChanged(start, mData.size());
    }
}
